package simpleparser

import (
	"errors"
	"fmt"
)

func Parse(tokenLists []*TokenList) (ret *AstNode, err error) {
	ret = &AstNode{Type: ProgramRoot}

	for _, tokenList := range tokenLists {
		v, err := ParseItem(tokenList)
		if err != nil {
			break
		}

		ret.Children = append(ret.Children, v)
	}

	return ret, err
}

func ParseItem(tokenList *TokenList) (ret *AstNode, err error) {
	// 按顺序依次匹配合法的模式
	ret, err = matchIntDeclare(tokenList)
	if err == nil {
		return ret, nil
	}

	ret, err = matchIntExpression(tokenList)
	if err == nil {
		return ret, nil
	}

	ret, err = matchIntAssignment(tokenList)
	if err == nil {
		return ret, nil
	}

	return ret, err
}

func matchIntDeclare(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	token := tokenList.Peek()
	if token.Type != INT {
		return root, errors.New("Expected integer identifier")
	}
	tokenList.Next()

	token = tokenList.Peek()
	if token == nil || token.Type != ID {
		tokenList.setPosition(pos)
		return root, errors.New("Expected identifier")
	}
	tokenList.Next()

	root = &AstNode{Type: DeclareInt, Value: token.Value}

	token = tokenList.Peek()
	if token == nil {
		return root, nil
	}

	if token.Type != ASSIGNMENT {
		tokenList.setPosition(pos)
		return root, errors.New("Expected assignment")
	}
	tokenList.Next()

	newNode, err := matchAddExpression(tokenList)
	if err != nil {
		tokenList.setPosition(pos)
		return root, err
	}

	root.Children = append(root.Children, newNode)

	// 结尾是空或者;分隔符
	token = tokenList.Peek()
	if token != nil && token.Type != SEMICOLON {
		tokenList.setPosition(pos)
		return root, errors.New("Expected valid end of expression")
	}

	tokenList.Next()
	return root, nil
}

func matchIntAssignment(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	token := tokenList.Peek()
	if token == nil || token.Type != ID {
		tokenList.setPosition(pos)
		return root, errors.New("Expected identifier")
	}
	tokenList.Next()

	root = &AstNode{Type: AssignmentInt, Value: token.Value}

	token = tokenList.Peek()
	if token == nil {
		return root, nil
	}

	if token.Type != ASSIGNMENT {
		tokenList.setPosition(pos)
		return root, errors.New("Expected assignment")
	}
	tokenList.Next()

	newNode, err := matchAddExpression(tokenList)
	if err != nil {
		tokenList.setPosition(pos)
		return root, err
	}

	root.Children = append(root.Children, newNode)

	// 结尾是空或者;分隔符
	token = tokenList.Peek()
	if token != nil && token.Type != SEMICOLON {
		tokenList.setPosition(pos)
		return root, errors.New("Expected valid end of expression")
	}

	tokenList.Next()
	return root, nil
}

func matchIntExpression(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	root, err := matchAddExpression(tokenList)
	if err != nil {
		return root, err
	}

	// 结尾是空或者;分隔符
	token := tokenList.Peek()
	if token != nil && token.Type != SEMICOLON {
		tokenList.setPosition(pos)
		return root, errors.New("Expected valid end of expression")
	}

	tokenList.Next()
	return root, nil
}

func matchAddExpression(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()
	newNode, err := matchMultiExpression(tokenList)
	if err != nil {
		return root, err
	}

	root = newNode
	var newNode2 *AstNode

	for {
		token := tokenList.Peek()
		if token == nil {
			break
		}

		if token.Type != PLUS && token.Type != MINUS {
			break
		}
		tokenList.Next()

		if token.Type == PLUS {
			root = &AstNode{Type: ExprAdd, Value: token.Value}
		} else {
			root = &AstNode{Type: ExprSub, Value: token.Value}
		}

		newNode2, err = matchMultiExpression(tokenList)
		if err != nil {
			tokenList.setPosition(pos)
			break
		}

		root.Children = append(root.Children, newNode)
		root.Children = append(root.Children, newNode2)

		// 注意，新节点在顶层，保证正确的结合性
		newNode = root
	}

	return root, err
}

func matchMultiExpression(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()
	newNode, err := matchPrimary(tokenList)
	if err != nil {
		return root, err
	}

	root = newNode
	var newNode2 *AstNode

	for {
		// 只有一个参数
		token := tokenList.Peek()
		if token == nil {
			break
		}

		if token.Type != STAR && token.Type != SLASH {
			break
		}
		tokenList.Next()

		if token.Type == STAR {
			root = &AstNode{Type: ExprMul, Value: token.Value}
		} else {
			root = &AstNode{Type: ExprDiv, Value: token.Value}
		}

		newNode2, err = matchPrimary(tokenList)
		if err != nil {
			tokenList.setPosition(pos)
			break
		}

		root.Children = append(root.Children, newNode)
		root.Children = append(root.Children, newNode2)

		// 注意，新节点在顶层，保证正确的结合性
		newNode = root
	}

	return root, err
}

func matchPrimary(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	token := tokenList.Peek()
	if token == nil {
		return root, errors.New("Unexpected end of input")
	}

	switch token.Type {
	case LPAREN:
		tokenList.Next()

		newNode, err := matchAddExpression(tokenList)
		if err != nil {
			tokenList.setPosition(pos)
			return root, err
		}

		token = tokenList.Peek()
		if token.Type != RPAREN {
			tokenList.setPosition(pos)
			return root, errors.New("Expected  ')'")
		}
		tokenList.Next()

		return newNode, nil

	case INTLITERAL:
		newNode, err := matchToken(tokenList, INTLITERAL)
		if err != nil {
			return root, err
		}

		return newNode, nil

	case ID:
		newNode, err := matchToken(tokenList, ID)
		if err != nil {
			return root, err
		}

		return newNode, nil
	}

	return root, nil
}

func matchToken(tokenList *TokenList, t TokenType) (*AstNode, error) {
	token := tokenList.Peek()
	if token != nil && token.Type == t {
		tokenList.Next()

		switch t {
		case ID:
			return &AstNode{Type: IdInt, Value: token.Value}, nil

		case INTLITERAL:
			return &AstNode{Type: LiteralInt, Value: token.Value}, nil

		default:
			return nil, errors.New(fmt.Sprintf("Not support match token %v", t))
		}
	} else {
		return nil, errors.New(fmt.Sprintf("Expected %v, got %v", t, token))
	}
}
